package ltd.dujiabao.billingservice.listener;

import lombok.extern.slf4j.Slf4j;
import ltd.dujiabao.billingservice.dao.AccountBalanceRepository;
import ltd.dujiabao.billingservice.dao.BalanceLogRepository;
import ltd.dujiabao.billingservice.domain.entity.BalanceLog;
import ltd.dujiabao.billingservice.domain.enums.TransactionType;
import ltd.dujiabao.common.event.BillingDeductedEvent;
import ltd.dujiabao.common.event.BillingFailedEvent;
import ltd.dujiabao.common.event.InventoryDeductedEvent;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * @author Bowie Du
 * @date 2025/7/14 22:19
 */
@Slf4j
@Component
public class BillingListener {
    @Autowired
    private AccountBalanceRepository balanceRepository;

    @Autowired
    private BalanceLogRepository balanceLogRepository;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @RabbitListener(
            bindings = @QueueBinding(
                    value = @Queue(
                            value = "billing.queue",
                            durable = "true"
                    ),
                    exchange = @Exchange(
                            value = "inventory.success.exchange",
                            durable = "true",
                            type = ExchangeTypes.FANOUT
                    )
            )
    )
    @Transactional(rollbackFor = Exception.class)
    public void handleInventoryDeductedEvent(InventoryDeductedEvent event) {
        // 扣除余额
        boolean isSuccess = balanceRepository.decrementBalance(event.getUserId(), event.getAmount()) > 0;

        // 保存流水
        if (isSuccess) {
            BalanceLog balanceLog = new BalanceLog()
                    .setOrderId(event.getOrderId())
                    .setTransactionType(TransactionType.PAYMENT.name())
                    .setUserId(event.getUserId())
                    .setAmount(event.getAmount())
                    .setCreatedAt(LocalDateTime.now())
                    .setUpdatedAt(LocalDateTime.now());
            balanceLogRepository.save(balanceLog);
        }

        // 发布事件
        if (isSuccess) {
            BillingDeductedEvent deductedEvent = BillingDeductedEvent.builder()
                    .orderId(event.getOrderId())
                    .build();
            rabbitTemplate.convertAndSend("billing.success.exchange", "", deductedEvent);
        } else {
            BillingFailedEvent failedEvent = BillingFailedEvent.builder()
                    .orderId(event.getOrderId())
                    .reason("Failed to deduct balance.")
                    .build();
            rabbitTemplate.convertAndSend("billing.fail.exchange", "", failedEvent);
        }

        log.info("deduct balance orderId {} result {}", event.getOrderId(), isSuccess);
    }
}
